package com.example.firstapp.core;

import java.util.List;

import com.example.firstapp.entity.Restaurant;
import com.example.firstapp.entity.RestaurantReview;

public class SocialContext implements UserContext {

	private static final double RATE_WEIGHT = 7;
	private static final double NUMBER_OF_VIEW_WEIGHT = 3;
	private List<Restaurant> restaurants;
	private double max = 0.0, min = 100.0;
	int totalReview = 0;
	double totalAvgRate = 0.0;

	public SocialContext(List<Restaurant> restaurants) {
		this.restaurants = restaurants;

		// calculate total review and total avg rate

		for (Restaurant restaurant : restaurants) {
			totalReview += restaurant.getReviews().size();
			totalAvgRate += calculateAverageRate(restaurant);
		}

		// find max and min internal rate
		for (Restaurant restaurant : restaurants) {
			double internalRate = calculateInternalRate(restaurant);
			if (min > internalRate)
				min = internalRate;
			if (max < internalRate)
				max = internalRate;
		}
	}

	@Override
	public double evaluate(Restaurant restaurant) {
		// return 10 for the best, 0 for the worst
		double internalRate = calculateInternalRate(restaurant);
		if (Double.compare(max, min) == 0)
			return 10.0;
		return 10.0 * (internalRate - min) / (max - min);
	}

	private double calculateInternalRate(Restaurant restaurant) {
		List<RestaurantReview> reviews = restaurant.getReviews();
		double avgRate = calculateAverageRate(restaurant);
		return RATE_WEIGHT * avgRate / totalAvgRate + NUMBER_OF_VIEW_WEIGHT
				* reviews.size() / totalReview;
	}

	private double calculateAverageRate(Restaurant restaurant) {
		List<RestaurantReview> reviews = restaurant.getReviews();
		double averageRate = 2.5; // from 0 to 5, default value is 2.5 if there
		// is no reviews
		if (reviews != null && reviews.size() > 0) {
			double sum = 0.0;
			// calculate sum of rate
			for (RestaurantReview review : reviews) {
				sum += review.getStar();
			}
			averageRate = sum / (double) (reviews.size());
		}
		return averageRate;
	}
}
